#include <iostream>
#include <string>
#include <google/protobuf/map.h>
#include <sstream>
#include <fstream>
#include <random>
#include "../ContactException.h"
#include "../cpp-httplib-master/httplib.h"
#include "../proto/contact_service.pb.h"


class Utils{
public:
    static unsigned int random_char(){
        // 用于随机数引擎获得随机种⼦
        std::random_device rd;
        // mt19937是c++11新特性，它是⼀种随机数算法，用法与rand()函数类似，但是mt19937 具有速度快，周期长的特点
        // 作用是生成伪随机数
        std::mt19937 gen(rd());
        // 随机生成⼀个整数i 范围[0, 255]
        std::uniform_int_distribution<> dis(0, 255);
        return dis(gen);
    }
    // 生成 UUID （通用唯⼀标识符）
    static std::string generate_hex(const unsigned int len){
        std::stringstream ss;
        // 生成 len 个16进制随机数，将其拼接而成
        for (auto i = 0; i < len; i++){
            const auto rc = random_char();
            std::stringstream hexstream;
            hexstream << std::hex << rc;
            auto hex = hexstream.str();
            ss << (hex.length() < 2 ? '0' + hex : hex);
        }
        return ss.str();
    }
    static void map_copy(google::protobuf::Map<std::string, std::string> *target, const google::protobuf::Map<std::string, std::string> &source){
        if (nullptr == target){
            std::cout << "map_copy warning, target is nullptr!" << std::endl;
            return;
        }
        for (auto it = source.cbegin(); it != source.cend(); ++it){
            target->insert({it->first, it->second});
        }
    }
};

// 从文件加载联系人数据
contact_service::Contacts LoadContactsFromFile() {
    contact_service::Contacts contacts;
    std::fstream input("contacts.bin", std::ios::in | std::ios::binary);
    if (input) {
        contacts.ParseFromIstream(&input);
    }
    input.close();
    return contacts;
}

// 将联系人数据写入文件
void SaveContactsToFile(const contact_service::Contacts& contacts) {
    std::fstream output("contacts.bin", std::ios::out | std::ios::binary | std::ios::trunc);
    if (!output)  throw ContactsException("无法打开 contacts.bin 进行写入");
    if (!contacts.SerializeToOstream(&output))  throw ContactsException("序列化失败");
    output.close();
}

// 根据 contact_id 查找联系人索引
int FindContactIndexById(contact_service::Contacts& contacts, const std::string& contact_id) {
    for (int i = 0; i < contacts.info_size(); ++i) {
        if (contacts.info(i).name() == contact_id) return i;
    }
    return -1;
}

void PrintContact(const contact_service::AddContactRequest &req){
    const contact_service::ContactInfo& info = req.info();
    std::cout << "姓名: " << info.name() << std::endl;
    std::cout << "年龄: " << info.age() << std::endl;
    for(int j = 0; j < info.number_size(); ++j){
        std::cout << "电话 " << j + 1 << ": " << info.number(j) << std::endl;
    }
}

void AddService(httplib::Server &server){
    server.Post("/contacts/add", [](const httplib::Request &req, httplib::Response &resp) {
        std::cout << "接收到 post 请求!" << std::endl;
        // 反序列化 request req.body
        contact_service::AddContactRequest request;
        contact_service::AddContactResponse response;
        contact_service::BaseResponse* base = new contact_service::BaseResponse();

        try {
            if(!request.ParseFromString(req.body)) {
                throw ContactsException("AddContactRequest 反序列化失败! ");
            }
    
            // 新增联系人，持久化存储通讯录  ----> 打印新增的联系人信息
            PrintContact(request); // 调试
            
           // 1. 加载现有联系人数据
            contact_service::Contacts contacts = LoadContactsFromFile();

            // 2. 生成唯一 ID
            std::string contact_id = Utils::generate_hex(10);

            // 3. 设置联系人 ID（用作唯一标识）
            contact_service::ContactInfo info = request.info();  // 复制 info
            info.set_contact_id(contact_id);  // 将 ID 存入 name 字段（模拟）
            info.set_name(request.info().name());

            // 4. 添加到联系人列表
            // *contacts.add_info() = info;
            contacts.add_info()->CopyFrom(info);

            // 5. 写入文件
            SaveContactsToFile(contacts);

            // 6. 构造响应
            base->set_success(true);
            response.set_allocated_base_resp(base);
            response.set_contact_id(contact_id);

            // 7. 序列化响应
            std::string response_str;
            if (!response.SerializeToString(&response_str)) {
                throw ContactsException("AddContactResponse 序列化失败");
            }

            resp.status = 200;
            resp.body = response_str;
            resp.set_header("Content-Type", "application/protobuf");
        } catch (const ContactsException &e) {            
            base->set_success(false);
            base->set_error_desc(e.what());
            response.set_allocated_base_resp(base);

            std::string response_str;
            if(response.SerializeToString(&response_str)) {
                resp.body = response_str;
                resp.set_header("Content-Type", "application/protobuf");
            }

            resp.status = 500;
            std::cout << "新增联系人异常：" << e.what() << std::endl;
        } 
    });
}

void DelService(httplib::Server& server){
    // 删除联系人
    server.Post("/contacts/del", [](const httplib::Request& req, httplib::Response& resp) {
        contact_service::DelContactRequest request;
        contact_service::DelContactResponse response;
        contact_service::BaseResponse* base = new contact_service::BaseResponse();

        try {
            if (!request.ParseFromString(req.body)) {
                throw ContactsException("DelContactRequest 反序列化失败");
            }

            contact_service::Contacts contacts = LoadContactsFromFile();
            int index = -1;

            for (int i = 0; i < contacts.info_size(); ++i) {
                if (contacts.info(i).contact_id() == request.contact_id()) {
                    index = i;
                    break;
                }
            }

            if (index == -1) {
                base->set_success(false);
                base->set_error_desc("联系人不存在");
                response.set_allocated_base_resp(base);
                response.set_contact_id(request.contact_id());

                std::string response_str;
                if (response.SerializeToString(&response_str)) {
                    resp.body = response_str;
                    resp.set_header("Content-Type", "application/protobuf");
                }
                resp.status = 404;
                return;
            }

            // 删除联系人
            contacts.mutable_info()->DeleteSubrange(index, 1);
            SaveContactsToFile(contacts);

            base->set_success(true);
            response.set_allocated_base_resp(base);
            response.set_contact_id(request.contact_id());

            std::string response_str;
            if (!response.SerializeToString(&response_str)) {
                throw ContactsException("DelContactResponse 序列化失败");
            }

            resp.status = 200;
            resp.body = response_str;
            resp.set_header("Content-Type", "application/protobuf");

        } catch (const ContactsException& e) {
            base->set_success(false);
            base->set_error_desc(e.what());
            response.set_allocated_base_resp(base);
            std::string response_str;
            if (response.SerializeToString(&response_str)) {
                resp.body = response_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
            resp.status = 500;
            std::cerr << "删除联系人异常: " << e.what() << std::endl;
        }
    });
    return;
}

void Find_one_Service(httplib::Server &server){
    // 查询单个联系人
    server.Post("/contacts/get", [](const httplib::Request& req, httplib::Response& resp) {
        contact_service::FindOneContactRequest request;
        contact_service::FindOneContactResponse response;
        contact_service::BaseResponse* base = new contact_service::BaseResponse();

        try {
            if (!request.ParseFromString(req.body)) {
                throw ContactsException("FindOneContactRequest 反序列化失败");
            }

            contact_service::Contacts contacts = LoadContactsFromFile();
            bool found = false;

            for (const auto& info : contacts.info()) {
                if (info.name() == request.contact_id()) {
                    *response.mutable_info() = info;
                    response.set_contact_id(request.contact_id());
                    found = true;
                    break;
                }
            }

            base->set_success(found);
            if (!found) {
                base->set_error_desc("未找到联系人");
            }
            response.set_allocated_base_resp(base);

            std::string response_str;
            if (!response.SerializeToString(&response_str)) {
                throw ContactsException("FindOneContactResponse 序列化失败");
            }

            resp.status = 200;
            resp.body = response_str;
            resp.set_header("Content-Type", "application/protobuf");

        } catch (const ContactsException& e) {
            base->set_success(false);
            base->set_error_desc(e.what());
            response.set_allocated_base_resp(base);
            std::string response_str;
            if (response.SerializeToString(&response_str)) {
                resp.body = response_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
            resp.status = 500;
            std::cerr << "查询单个联系人异常: " << e.what() << std::endl;
        }
    });
    return ;
}

void Find_All_Service(httplib::Server &server){
    // 查询所有联系人
    server.Post("/contacts/all", [](const httplib::Request& req, httplib::Response& resp) {
        contact_service::FindAllContactsResponse response;
        contact_service::BaseResponse* base = new contact_service::BaseResponse();

        try {
            contact_service::Contacts contacts = LoadContactsFromFile();

            base->set_success(true);
            response.set_allocated_base_resp(base);

            for (const auto& info : contacts.info()) {
                contact_service::PeopleInfo* people = response.add_contacts();
                people->set_contact_id(info.contact_id());  // 使用 name 作为 ID
                *people->mutable_info() = info;
            }

            std::string response_str;
            if (!response.SerializeToString(&response_str)) {
                throw ContactsException("FindAllContactsResponse 序列化失败");
            }

            resp.status = 200;
            resp.body = response_str;
            resp.set_header("Content-Type", "application/protobuf");

        } catch (const ContactsException& e) {
            base->set_success(false);
            base->set_error_desc(e.what());
            response.set_allocated_base_resp(base);
            std::string response_str;
            if (response.SerializeToString(&response_str)) {
                resp.body = response_str;
                resp.set_header("Content-Type", "application/protobuf");
            }
            resp.status = 500;
            std::cerr << "查询所有联系人异常: " << e.what() << std::endl;
        }
    });
    return;
}

int main(){
    std::cout << "——————————————————服务启动——————————————————" << std::endl;    
    httplib::Server server;

    AddService(server);
    DelService(server);
    Find_one_Service(server);
    Find_All_Service(server);

    // 绑定指定端口, 并将端口号开放
    server.listen("0.0.0.0", 8082);

    return 0;
}